package org.gdstash.db;

import org.gdstash.util.GDLog;
import org.gdstash.util.GDMsgFormatter;

import java.util.LinkedList;
import java.util.List;

public class SelectionCriteria {
    public SelectionMode selMode;
    public CombinationMode combiMode;
    public SoulboundMode soulboundMode;
    public List<String> itemIDs;
    public List<String> itemClass;
    public List<String> armorClass;
    public List<String> artifactClass;
    public List<String> itemRarity;
    public List<String> itemStyle;
    public String itemName;
    public boolean setItem;
    public String bonusSkill;
    public boolean allSkills;
    public boolean masteryBonusSkills;
    public String modifiedSkill;
    public boolean masteryModifySkills;
    public boolean allItemSkills;
    public String itemSkill;
    public String prefixID;
    public String suffixID;
    public int levelMin;
    public int levelMax;
    public int cunningMax;
    public int physiqueMax;
    public int spiritMax;
    public String dmgConversionFrom;
    public String dmgConversionTo;
    public boolean noEnemyOnly;
    public DamageClassInfo dmgClassInfo;
    public FieldInfo fieldInfo;
    public List<StatInfo> statInfos;
    public boolean slotAxe1H;
    public boolean slotAxe2H;
    public boolean slotDagger1H;
    public boolean slotMace1H;
    public boolean slotMace2H;
    public boolean slotScepter1H;
    public boolean slotSpear1H;
    public boolean slotSpear2H;
    public boolean slotStaff2H;
    public boolean slotSword1H;
    public boolean slotSword2H;
    public boolean slotRanged1H;
    public boolean slotRanged2H;
    public boolean slotShield;
    public boolean slotOffhand;
    public boolean slotAmulet;
    public boolean slotBelt;
    public boolean slotMedal;
    public boolean slotRing;
    public boolean slotHead;
    public boolean slotShoulders;
    public boolean slotChest;
    public boolean slotHands;
    public boolean slotLegs;
    public boolean slotFeet;
    public boolean petBonus;

    public SelectionCriteria() {
        this.selMode = SelectionMode.ITEM;
        this.combiMode = CombinationMode.OR;
        this.itemIDs = null;
        this.itemClass = new LinkedList<String>();
        this.armorClass = new LinkedList<String>();
        this.artifactClass = new LinkedList<String>();
        this.itemRarity = new LinkedList<String>();
        this.itemStyle = new LinkedList<String>();
        this.itemName = null;
        this.setItem = false;
        this.bonusSkill = null;
        this.allSkills = false;
        this.masteryBonusSkills = false;
        this.modifiedSkill = null;
        this.masteryModifySkills = false;
        this.allItemSkills = false;
        this.itemSkill = null;
        this.prefixID = null;
        this.suffixID = null;
        this.levelMin = -1;
        this.levelMax = -1;
        this.cunningMax = -1;
        this.physiqueMax = -1;
        this.spiritMax = -1;
        this.noEnemyOnly = true;
        this.dmgClassInfo = new DamageClassInfo();
        this.fieldInfo = new FieldInfo();
        this.statInfos = new LinkedList<StatInfo>();
        this.slotAxe1H = false;
        this.slotAxe2H = false;
        this.slotDagger1H = false;
        this.slotMace1H = false;
        this.slotMace2H = false;
        this.slotScepter1H = false;
        this.slotSword1H = false;
        this.slotSword2H = false;
        this.slotRanged1H = false;
        this.slotRanged2H = false;
        this.slotShield = false;
        this.slotOffhand = false;
        this.slotAmulet = false;
        this.slotBelt = false;
        this.slotMedal = false;
        this.slotRing = false;
        this.slotHead = false;
        this.slotShoulders = false;
        this.slotChest = false;
        this.slotHands = false;
        this.slotLegs = false;
        this.slotFeet = false;
        this.petBonus = false;
    }

    public void checkCriteria(final GDLog log) {
        if (this.selMode != SelectionMode.AFFIX && (this.itemIDs == null || this.itemIDs.isEmpty()) && (this.itemClass == null || this.itemClass.isEmpty())) {
            log.addError(GDMsgFormatter.getString(GDMsgFormatter.rbUI, "ERR_SEL_ITEM_TYPE"));
        }
        if ((this.dmgClassInfo.defense || this.dmgClassInfo.offense || this.dmgClassInfo.retaliation) && (this.statInfos == null || this.statInfos.isEmpty()) && !this.petBonus) {
            log.addError(GDMsgFormatter.getString(GDMsgFormatter.rbUI, "ERR_SEL_DMG_COMBI"));
        }
    }

    public boolean isInitial() {
        return (this.itemIDs == null || this.itemIDs.isEmpty()) && (this.itemClass == null || this.itemClass.isEmpty()) && (this.armorClass == null || this.armorClass.isEmpty()) && (this.artifactClass == null || this.artifactClass.isEmpty()) && (this.itemRarity == null || this.itemRarity.isEmpty()) && (this.itemStyle == null || this.itemStyle.isEmpty()) && this.itemName == null && !this.setItem && this.bonusSkill == null && !this.allSkills && !this.masteryBonusSkills && this.modifiedSkill == null && !this.masteryModifySkills && !this.allItemSkills && this.itemSkill == null && this.prefixID == null && this.suffixID == null && this.levelMin <= -1 && this.levelMax <= -1 && this.cunningMax <= -1 && this.physiqueMax <= -1 && this.spiritMax <= -1 && this.dmgConversionFrom == null && this.dmgConversionTo == null && (this.statInfos == null || this.statInfos.isEmpty()) && !this.slotAxe1H && !this.slotAxe2H && !this.slotDagger1H && !this.slotMace1H && !this.slotMace2H && !this.slotScepter1H && !this.slotSpear1H && !this.slotSpear2H && !this.slotStaff2H && !this.slotSword1H && !this.slotSword2H && !this.slotRanged1H && !this.slotShield && !this.slotOffhand && !this.slotAmulet && !this.slotBelt && !this.slotMedal && !this.slotRing && !this.slotHead && !this.slotShoulders && !this.slotChest && !this.slotHands && !this.slotLegs && !this.slotFeet && !this.petBonus;
    }

    public boolean isDamageClassUsed() {
        return this.dmgClassInfo.defense || this.dmgClassInfo.offense || this.dmgClassInfo.retaliation;
    }

    public boolean isStatTypeUsed() {
        return !this.statInfos.isEmpty();
    }

    public boolean isSkillBonusUsed() {
        return this.bonusSkill != null;
    }

    public boolean isAllSkillsUsed() {
        return this.allSkills;
    }

    public boolean isMasteryBonusSkillsUsed() {
        return this.masteryBonusSkills;
    }

    public boolean isSkillModifierUsed() {
        return this.modifiedSkill != null;
    }

    public boolean isMasteryModifySkillsUsed() {
        return this.masteryModifySkills;
    }

    public boolean isAllItemSkillsUsed() {
        return this.allItemSkills;
    }

    public boolean isItemSkillsUsed() {
        return this.itemSkill != null;
    }

    public boolean isPrefixUsed() {
        return this.prefixID != null;
    }

    public boolean isSuffixUsed() {
        return this.suffixID != null;
    }

    private static List<String> determineDamageTypes(final DamageClassInfo dmgClassInfo, final FieldInfo fieldInfo, final int statType) {
        final List<String> list = new LinkedList<String>();
        if (statType == 301) {
            if (!dmgClassInfo.defense && !dmgClassInfo.offense && !dmgClassInfo.retaliation) {
                list.add("offensiveBasePoison");
                list.add("offensivePoison");
            } else {
                if (dmgClassInfo.defense) {
                    list.add("defensivePoison");
                    if (fieldInfo.maxResist && !list.contains("defensiveAll")) {
                        list.add("defensiveAll");
                    }
                }
                if (dmgClassInfo.offense) {
                    list.add("offensiveBasePoison");
                    list.add("offensivePoison");
                }
                if (dmgClassInfo.retaliation) {
                    list.add("retaliationPoison");
                }
            }
        }
        if (statType == 302) {
            if (!dmgClassInfo.defense && !dmgClassInfo.offense && !dmgClassInfo.retaliation) {
                list.add("offensiveBaseAether");
                list.add("offensiveAether");
            } else {
                if (dmgClassInfo.defense) {
                    list.add("defensiveAether");
                    if (fieldInfo.maxResist && !list.contains("defensiveAll")) {
                        list.add("defensiveAll");
                    }
                }
                if (dmgClassInfo.offense) {
                    list.add("offensiveBaseAether");
                    list.add("offensiveAether");
                }
                if (dmgClassInfo.retaliation) {
                    list.add("retaliationAether");
                }
            }
        }
        if (statType == 303) {
            if (!dmgClassInfo.defense && !dmgClassInfo.offense && !dmgClassInfo.retaliation) {
                list.add("offensiveBaseChaos");
                list.add("offensiveChaos");
            } else {
                if (dmgClassInfo.defense) {
                    list.add("defensiveChaos");
                    if (fieldInfo.maxResist && !list.contains("defensiveAll")) {
                        list.add("defensiveAll");
                    }
                }
                if (dmgClassInfo.offense) {
                    list.add("offensiveBaseChaos");
                    list.add("offensiveChaos");
                }
                if (dmgClassInfo.retaliation) {
                    list.add("retaliationChaos");
                }
            }
        }
        if (statType == 304) {
            if (!dmgClassInfo.defense && !dmgClassInfo.offense && !dmgClassInfo.retaliation) {
                list.add("offensiveBaseCold");
                list.add("offensiveCold");
            } else {
                if (dmgClassInfo.defense) {
                    list.add("defensiveCold");
                    if (fieldInfo.maxResist && !list.contains("defensiveAll")) {
                        list.add("defensiveAll");
                    }
                }
                if (dmgClassInfo.offense) {
                    list.add("offensiveBaseCold");
                    list.add("offensiveCold");
                }
                if (dmgClassInfo.retaliation) {
                    list.add("retaliationCold");
                }
            }
        }
        if (statType == 305) {
            if (!dmgClassInfo.defense && !dmgClassInfo.offense && !dmgClassInfo.retaliation) {
                list.add("offensiveElemental");
            } else {
                if (dmgClassInfo.defense) {
                    list.add("defensiveElemental");
                    list.add("defensiveElementalResistance");
                    if (fieldInfo.maxResist && !list.contains("defensiveAll")) {
                        list.add("defensiveAll");
                    }
                }
                if (dmgClassInfo.offense) {
                    list.add("offensiveElemental");
                }
                if (dmgClassInfo.retaliation) {
                    list.add("retaliationElemental");
                }
            }
        }
        if (statType == 306) {
            if (!dmgClassInfo.defense && !dmgClassInfo.offense && !dmgClassInfo.retaliation) {
                list.add("offensiveBaseFire");
                list.add("offensiveFire");
            } else {
                if (dmgClassInfo.defense) {
                    list.add("defensiveFire");
                    if (fieldInfo.maxResist && !list.contains("defensiveAll")) {
                        list.add("defensiveAll");
                    }
                }
                if (dmgClassInfo.offense) {
                    list.add("offensiveBaseFire");
                    list.add("offensiveFire");
                }
                if (dmgClassInfo.retaliation) {
                    list.add("retaliationFire");
                }
            }
        }
        if (statType == 307) {
            if (!dmgClassInfo.defense && !dmgClassInfo.offense && !dmgClassInfo.retaliation) {
                list.add("offensiveBaseLife");
                list.add("offensiveLife");
            } else {
                if (dmgClassInfo.defense) {
                    list.add("defensiveLife");
                    if (fieldInfo.maxResist && !list.contains("defensiveAll")) {
                        list.add("defensiveAll");
                    }
                }
                if (dmgClassInfo.offense) {
                    list.add("offensiveBaseLife");
                    list.add("offensiveLife");
                }
                if (dmgClassInfo.retaliation) {
                    list.add("retaliationLife");
                }
            }
        }
        if (statType == 308) {
            if (!dmgClassInfo.defense && !dmgClassInfo.offense && !dmgClassInfo.retaliation) {
                list.add("offensiveBaseLightning");
                list.add("offensiveLightning");
            } else {
                if (dmgClassInfo.defense) {
                    list.add("defensiveLightning");
                    if (fieldInfo.maxResist && !list.contains("defensiveAll")) {
                        list.add("defensiveAll");
                    }
                }
                if (dmgClassInfo.offense) {
                    list.add("offensiveBaseLightning");
                    list.add("offensiveLightning");
                }
                if (dmgClassInfo.retaliation) {
                    list.add("retaliationLightning");
                }
            }
        }
        if (statType == 309) {
            if (!dmgClassInfo.defense && !dmgClassInfo.offense && !dmgClassInfo.retaliation) {
                list.add("offensivePhysical");
                list.add("offensiveBonusPhysical");
            } else {
                if (dmgClassInfo.defense) {
                    list.add("defensivePhysical");
                    if (fieldInfo.maxResist && !list.contains("defensiveAll")) {
                        list.add("defensiveAll");
                    }
                }
                if (dmgClassInfo.offense) {
                    list.add("offensivePhysical");
                    list.add("offensiveBonusPhysical");
                }
                if (dmgClassInfo.retaliation) {
                    list.add("retaliationPhysical");
                }
            }
        }
        if (statType == 310) {
            if (!dmgClassInfo.defense && !dmgClassInfo.offense && !dmgClassInfo.retaliation) {
                list.add("offensivePierce");
            } else {
                if (dmgClassInfo.defense) {
                    list.add("defensivePierce");
                    if (fieldInfo.maxResist && !list.contains("defensiveAll")) {
                        list.add("defensiveAll");
                    }
                }
                if (dmgClassInfo.offense) {
                    list.add("offensivePierce");
                }
                if (dmgClassInfo.retaliation) {
                    list.add("retaliationPierce");
                }
            }
        }
        if (statType == 401) {
            if (!dmgClassInfo.defense && !dmgClassInfo.offense && !dmgClassInfo.retaliation) {
                list.add("offensiveSlowPoison");
            } else {
                if (dmgClassInfo.defense) {
                    if (!list.contains("defensivePoison")) {
                        list.add("defensivePoison");
                    }
                    if (fieldInfo.maxResist && !list.contains("defensiveAll")) {
                        list.add("defensiveAll");
                    }
                }
                if (dmgClassInfo.offense) {
                    list.add("offensiveSlowPoison");
                }
                if (dmgClassInfo.retaliation) {
                    list.add("retaliationSlowPoison");
                }
            }
        }
        if (statType == 404) {
            if (!dmgClassInfo.defense && !dmgClassInfo.offense && !dmgClassInfo.retaliation) {
                list.add("offensiveSlowCold");
            } else {
                if (dmgClassInfo.defense) {
                    if (!list.contains("defensiveCold")) {
                        list.add("defensiveCold");
                    }
                    if (fieldInfo.maxResist && !list.contains("defensiveAll")) {
                        list.add("defensiveAll");
                    }
                }
                if (dmgClassInfo.offense) {
                    list.add("offensiveSlowCold");
                }
                if (dmgClassInfo.retaliation) {
                    list.add("retaliationSlowCold");
                }
            }
        }
        if (statType == 406) {
            if (!dmgClassInfo.defense && !dmgClassInfo.offense && !dmgClassInfo.retaliation) {
                list.add("offensiveSlowFire");
            } else {
                if (dmgClassInfo.defense) {
                    if (!list.contains("defensiveFire")) {
                        list.add("defensiveFire");
                    }
                    if (fieldInfo.maxResist && !list.contains("defensiveAll")) {
                        list.add("defensiveAll");
                    }
                }
                if (dmgClassInfo.offense) {
                    list.add("offensiveSlowFire");
                }
                if (dmgClassInfo.retaliation) {
                    list.add("retaliationSlowFire");
                }
            }
        }
        if (statType == 407) {
            if (!dmgClassInfo.defense && !dmgClassInfo.offense && !dmgClassInfo.retaliation) {
                list.add("offensiveSlowLife");
            } else {
                if (dmgClassInfo.defense) {
                    if (!list.contains("defensiveLife")) {
                        list.add("defensiveLife");
                    }
                    if (fieldInfo.maxResist && !list.contains("defensiveAll")) {
                        list.add("defensiveAll");
                    }
                }
                if (dmgClassInfo.offense) {
                    list.add("offensiveSlowLife");
                }
                if (dmgClassInfo.retaliation) {
                    list.add("retaliationSlowLife");
                }
            }
        }
        if (statType == 408) {
            if (!dmgClassInfo.defense && !dmgClassInfo.offense && !dmgClassInfo.retaliation) {
                list.add("offensiveSlowLightning");
            } else {
                if (dmgClassInfo.defense) {
                    if (!list.contains("defensiveLightning")) {
                        list.add("defensiveLightning");
                    }
                    if (fieldInfo.maxResist && !list.contains("defensiveAll")) {
                        list.add("defensiveAll");
                    }
                }
                if (dmgClassInfo.offense) {
                    list.add("offensiveSlowLightning");
                }
                if (dmgClassInfo.retaliation) {
                    list.add("retaliationSlowLightning");
                }
            }
        }
        if (statType == 409) {
            if (!dmgClassInfo.defense && !dmgClassInfo.offense && !dmgClassInfo.retaliation) {
                list.add("offensiveSlowPhysical");
            } else {
                if (dmgClassInfo.defense) {
                    if (!list.contains("defensivePhysical")) {
                        list.add("defensivePhysical");
                    }
                    if (fieldInfo.maxResist && !list.contains("defensiveAll")) {
                        list.add("defensiveAll");
                    }
                }
                if (dmgClassInfo.offense) {
                    list.add("offensiveSlowPhysical");
                }
                if (dmgClassInfo.retaliation) {
                    list.add("retaliationSlowPhysical");
                }
            }
        }
        if (statType == 410) {
            if (!dmgClassInfo.defense && !dmgClassInfo.offense && !dmgClassInfo.retaliation) {
                list.add("offensiveSlowBleeding");
            } else {
                if (dmgClassInfo.defense) {
                    list.add("defensiveBleeding");
                    if (fieldInfo.maxResist && !list.contains("defensiveAll")) {
                        list.add("defensiveAll");
                    }
                }
                if (dmgClassInfo.offense) {
                    list.add("offensiveSlowBleeding");
                }
                if (dmgClassInfo.retaliation) {
                    list.add("retaliationSlowBleeding");
                }
            }
        }
        if (statType == 501) {
            if (!dmgClassInfo.defense && !dmgClassInfo.offense && !dmgClassInfo.retaliation) {
                list.add("offensiveTotalDamage");
            } else {
                if (dmgClassInfo.defense && !list.contains("defensiveAll")) {
                    list.add("defensiveAll");
                }
                if (dmgClassInfo.offense) {
                    list.add("offensiveTotalDamage");
                }
                if (dmgClassInfo.retaliation) {
                    list.add("retaliationTotalDamage");
                }
            }
        }
        if (statType == 502) {
            list.add("offensiveCritDamage");
        }
        if (statType == 503) {
            if (dmgClassInfo.defense) {
                list.add("defensiveSlowLifeLeach");
            }
            if (dmgClassInfo.offense) {
                list.add("offensiveLifeLeech");
                list.add("offensiveSlowLifeLeach");
            }
            if (dmgClassInfo.retaliation) {
                list.add("retaliationSlowLifeLeach");
            }
        }
        if (statType == 504 && !list.contains("defensiveReflect")) {
            list.add("defensiveReflect");
        }
        if (statType == 505) {
            if (!dmgClassInfo.defense && !dmgClassInfo.offense && !dmgClassInfo.retaliation) {
                if (!list.contains("offensiveSlowAttackSpeed")) {
                    list.add("offensiveSlowAttackSpeed");
                }
            } else {
                if ((dmgClassInfo.defense || dmgClassInfo.offense) && !list.contains("offensiveSlowAttackSpeed")) {
                    list.add("offensiveSlowAttackSpeed");
                }
                if (dmgClassInfo.retaliation) {
                    list.add("retaliationSlowAttackSpeed");
                }
            }
        }
        if (statType == 506 && !list.contains("offensiveSlowTotalSpeed")) {
            list.add("offensiveSlowTotalSpeed");
        }
        if (statType == 507) {
            if (!dmgClassInfo.defense && !dmgClassInfo.offense && !dmgClassInfo.retaliation) {
                if (!list.contains("offensiveSlowDefensiveAbility")) {
                    list.add("offensiveSlowDefensiveAbility");
                }
            } else {
                if ((dmgClassInfo.defense || dmgClassInfo.offense) && !list.contains("offensiveSlowDefensiveAbility")) {
                    list.add("offensiveSlowDefensiveAbility");
                }
                if (dmgClassInfo.retaliation) {
                    list.add("retaliationSlowDefensiveAbility");
                }
            }
        }
        if (statType == 508) {
            if (!dmgClassInfo.defense && !dmgClassInfo.offense && !dmgClassInfo.retaliation) {
                if (!list.contains("offensiveSlowOffensiveAbility")) {
                    list.add("offensiveSlowOffensiveAbility");
                }
            } else {
                if ((dmgClassInfo.defense || dmgClassInfo.offense) && !list.contains("offensiveSlowOffensiveAbility")) {
                    list.add("offensiveSlowOffensiveAbility");
                }
                if (dmgClassInfo.retaliation) {
                    list.add("retaliationSlowOffensiveAbility");
                }
            }
        }
        if (statType == 509 && !list.contains("piercingProjectile")) {
            list.add("piercingProjectile");
        }
        if (statType == 510 && !list.contains("offensiveTotalResistanceReductionAbsolute")) {
            list.add("offensiveTotalResistanceReductionAbsolute");
        }
        if (statType == 511 && !list.contains("offensiveTotalResistanceReductionPercent")) {
            list.add("offensiveTotalResistanceReductionPercent");
        }
        if (statType == 512 && !list.contains("offensivePhysicalResistanceReductionAbsolute")) {
            list.add("offensivePhysicalResistanceReductionAbsolute");
        }
        if (statType == 513 && !list.contains("offensivePhysicalResistanceReductionPercent")) {
            list.add("offensivePhysicalResistanceReductionPercent");
        }
        if (statType == 514 && !list.contains("offensiveElementalResistanceReductionAbsolute")) {
            list.add("offensiveElementalResistanceReductionAbsolute");
        }
        if (statType == 515 && !list.contains("offensiveElementalResistanceReductionPercent")) {
            list.add("offensiveElementalResistanceReductionPercent");
        }
        if (statType == 516 && !list.contains("defensivePercentReflectionResistance")) {
            list.add("defensivePercentReflectionResistance");
        }
        if (statType == 517 && !list.contains("skillManaCostReduction")) {
            list.add("skillManaCostReduction");
        }
        if (statType == 601) {
            if (!dmgClassInfo.defense && !dmgClassInfo.offense && !dmgClassInfo.retaliation) {
                list.add("offensiveStun");
            } else {
                if (dmgClassInfo.defense) {
                    list.add("defensiveStun");
                }
                if (dmgClassInfo.offense) {
                    list.add("offensiveStun");
                }
                if (dmgClassInfo.retaliation) {
                    list.add("retaliationStun");
                }
            }
        }
        if (statType == 602) {
            list.add("defensiveTotalSpeedResistance");
        }
        if (statType == 603) {
            if (!dmgClassInfo.defense && !dmgClassInfo.offense && !dmgClassInfo.retaliation) {
                list.add("offensiveTrap");
            } else {
                if (dmgClassInfo.defense) {
                    list.add("defensiveTrap");
                }
                if (dmgClassInfo.offense) {
                    list.add("offensiveTrap");
                }
                if (dmgClassInfo.retaliation) {
                    list.add("retaliationTrap");
                }
            }
        }
        if (statType == 604) {
            if (!dmgClassInfo.defense && !dmgClassInfo.offense && !dmgClassInfo.retaliation) {
                list.add("offensivePetrify");
            } else {
                if (dmgClassInfo.defense) {
                    list.add("defensivePetrify");
                }
                if (dmgClassInfo.offense) {
                    list.add("offensivePetrify");
                }
                if (dmgClassInfo.retaliation) {
                    list.add("retaliationPetrify");
                }
            }
        }
        if (statType == 605) {
            if (!dmgClassInfo.defense && !dmgClassInfo.offense && !dmgClassInfo.retaliation) {
                list.add("offensiveFreeze");
            } else {
                if (dmgClassInfo.defense) {
                    list.add("defensiveFreeze");
                }
                if (dmgClassInfo.offense) {
                    list.add("offensiveFreeze");
                }
                if (dmgClassInfo.retaliation) {
                    list.add("retaliationFreeze");
                }
            }
        }
        return list;
    }

    public static void addStatInfos(final SelectionCriteria criteria, final int statType) {
        final StatInfo info = new StatInfo(criteria, statType);
        criteria.statInfos.add(info);
    }

    public enum ComboType {
        AND,
        OR;
    }

    public static class StatInfo {
        public List<String> statTypes;
        public boolean flat;
        public boolean percentage;
        public boolean maxResist;
        public ComboType combo;

        public StatInfo(final SelectionCriteria criteria, final int statType) {
            this.statTypes = null;
            this.flat = false;
            this.percentage = false;
            this.maxResist = false;
            this.combo = ComboType.AND;
            this.statTypes = determineDamageTypes(criteria.dmgClassInfo, criteria.fieldInfo, statType);
            this.flat = criteria.fieldInfo.flat;
            this.percentage = criteria.fieldInfo.percentage;
            this.maxResist = criteria.fieldInfo.maxResist;
            this.combo = ComboType.AND;
            final boolean flagsFilled = criteria.fieldInfo.flat || criteria.fieldInfo.percentage || criteria.fieldInfo.maxResist;
            if (!flagsFilled) {
                this.flat = true;
                this.percentage = true;
            }
        }

        public StatInfo(final String statType, final boolean flat, final boolean percentage) {
            this(statType, flat, percentage, ComboType.AND);
        }

        public StatInfo(final String statType, boolean flat, boolean percentage, final ComboType combo) {
            this.statTypes = null;
            this.flat = false;
            this.percentage = false;
            this.maxResist = false;
            this.combo = ComboType.AND;
            (this.statTypes = new LinkedList<String>()).add(statType);
            this.flat = flat;
            this.percentage = percentage;
            this.maxResist = false;
            this.combo = combo;
            final boolean flagsFilled = flat || percentage;
            if (!flagsFilled) {
                flat = true;
                percentage = true;
            }
        }
    }

    public static class DamageClassInfo {
        public boolean offense;
        public boolean defense;
        public boolean retaliation;

        public DamageClassInfo() {
            this.offense = false;
            this.defense = false;
            this.retaliation = false;
        }
    }

    public static class FieldInfo {
        public boolean flat;
        public boolean percentage;
        public boolean maxResist;

        public FieldInfo() {
            this.flat = false;
            this.percentage = false;
            this.maxResist = false;
        }
    }

    public enum SelectionMode {
        ITEM,
        COMPONENT,
        AFFIX;
    }

    public enum CombinationMode {
        AND,
        OR;
    }

    public enum SoulboundMode {
        ALL,
        NONBOUND,
        SOULBOUND;
    }
}
